

// digipot wiring : http://arduino.cc/en/Tutorial/DigitalPotentiometer

#include "amp.h"


//#if defined(ORANGE_OR15)
//    #define MAX_INPUT_POTS          (5)
//    const char * INPUT_NAMES[MAX_INPUT_POTS]            = {"VOLUME",    "TREBLE",   "MID",      "BASS",     "GAIN"  };
//    const bool INPUT_IS_DUAL[MAX_INPUT_POTS]            = {0,           0,          0,          0,          1       };
//    const EPotType INPUT_TYPE[MAX_INPUT_POTS]           = {EPotLog,     EPotLin,    EPotLin,    EPotLog,    EPotLog };
//    const unsigned long INPUT_OHM[MAX_INPUT_POTS]       = {1 * MEGA,    250 * KILO, 25 * KILO,  500 * KILO, 1 * MEGA};
//    const unsigned long OUTPUT_OHM[MAX_INPUT_POTS]      = {1 * MEGA,    1 * MEGA,   100 * KILO, 1 * MEGA,   1 * MEGA};
//    const unsigned char INPUT_ADDRESS[MAX_INPUT_POTS]   = {A0,          A1,         A2,         A3,         A4      };
//    const unsigned char OUTPUT_ADDRESS[MAX_INPUT_POTS]  = {0x2c,        0x2d,       D2,         D3,         D4      };
//#elif defined(VOX_AC15)
//    #define MAX_INPUT_POTS          (8)
//    const char * INPUT_NAMES[MAX_INPUT_POTS]    = {"NORMAL VOL","BOOST VOL","BASS",     "TREBLE",   "TR SPEED", "TR DEPTH", "REVERB",   "MASTER"    };
//    const bool INPUT_IS_DUAL[MAX_INPUT_POTS]    = {0,           0,          0,          0,          0,          0,          0,          0           };
//    const EPotType INPUT_TYPE[MAX_INPUT_POTS]   = {EPotLog,     EPotLog,    EPotLog,    EPotLog,    EPotRLog,   EPotLin,    EPotLin,    EPotLog     };
//    const unsigned long INPUT_OHM[MAX_INPUT_POTS]         = {500 * KILO,  500 * KILO, 1 * MEGA,   1 * MEGA,   1 * MEGA,   500 * KILO, 100 * KILO, 500 * KILO  };
//    const unsigned long OUTPUT_OHM[MAX_INPUT_POTS]        = {1 * MEGA,    1 * MEGA,   1 * MEGA,   1 * MEGA,   1 * MEGA,   1 * MEGA,   100 * KILO, 1 * MEGA    };
//    const unsigned char INPUT_ADDRESS[MAX_INPUT_POTS]     = {A0,          A1,         A2,         A3,         A4,         A5,         A6,         A7          };
//    const unsigned char OUTPUT_ADDRESS[MAX_INPUT_POTS]    = {0x2c,        0x2d,       D2,         D3,         D4,         D5,         D6,         D7          };
//#elif
//#endif

// ==============================================================================
#pragma mark - GLOBALS
// ==============================================================================
#define             PIN_BLUETOOTH_RX    (D11)
#define             PIN_BLUETOOTH_TX    (D12)
#define             PIN_STATUS_LED      (D13)

SoftwareSerial      gBluetoothSerial(PIN_BLUETOOTH_RX, PIN_BLUETOOTH_TX);
float               LOG_TABLE[MAX_INPUT_STEPS] = {
0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000002, 0.000002, 0.000002, 0.000002, 0.000002, 0.000003, 0.000003, 0.000003, 0.000003, 0.000004, 0.000004, 0.000005, 0.000005, 0.000006, 0.000006, 0.000007, 0.000007, 0.000008, 0.000009, 0.000010, 0.000010, 0.000011, 0.000012, 0.000013, 0.000015, 0.000016, 0.000017, 0.000019, 0.000020, 0.000022, 0.000024, 0.000026, 0.000028, 0.000030, 0.000032, 0.000035, 0.000037, 0.000040, 0.000043, 0.000046, 0.000050, 0.000053, 0.000057, 0.000061, 0.000065, 0.000070, 0.000075, 0.000080, 0.000085, 0.000091, 0.000097, 0.000103, 0.000110, 0.000117, 0.000125, 0.000133, 0.000141, 0.000150, 0.000159, 0.000169, 0.000179, 0.000190, 0.000201, 0.000213, 0.000225, 0.000238, 0.000252, 0.000266, 0.000281, 0.000296, 0.000313, 0.000330, 0.000347, 0.000366, 0.000385, 0.000406, 0.000427, 0.000449, 0.000472, 0.000496, 0.000521, 0.000547, 0.000574, 0.000602, 0.000631, 0.000662, 0.000694, 0.000726, 0.000761, 0.000796, 0.000833, 0.000871, 0.000910, 0.000951, 0.000994, 0.001038, 0.001083, 0.001130, 0.001179, 0.001230, 0.001282, 0.001336, 0.001392, 0.001449, 0.001509, 0.001570, 0.001634, 0.001699, 0.001767, 0.001836, 0.001908, 0.001982, 0.002059, 0.002137, 0.002218, 0.002301, 0.002387, 0.002476, 0.002566, 0.002660, 0.002756, 0.002855, 0.002956, 0.003061, 0.003168, 0.003278, 0.003391, 0.003507, 0.003626, 0.003748, 0.003873, 0.004002, 0.004134, 0.004269, 0.004407, 0.004549, 0.004695, 0.004844, 0.004996, 0.005152, 0.005312, 0.005475, 0.005643, 0.005814, 0.005989, 0.006168, 0.006351, 0.006538, 0.006729, 0.006924, 0.007124, 0.007328, 0.007536, 0.007748, 0.007965, 0.008187, 0.008412, 0.008643, 0.008878, 0.009118, 0.009362, 0.009612, 0.009866, 0.010125, 0.010389, 0.010658, 0.010932, 0.011211, 0.011496, 0.011785, 0.012080, 0.012380, 0.012686, 0.012996, 0.013313, 0.013634, 0.013962, 0.014294, 0.014633, 0.014977, 0.015327, 0.015682, 0.016044, 0.016411, 0.016784, 0.017163, 0.017549, 0.017940, 0.018337, 0.018740, 0.019150, 0.019565, 0.019987, 0.020416, 0.020850, 0.021291, 0.021738, 0.022192, 0.022652, 0.023119, 0.023592, 0.024072, 0.024559, 0.025052, 0.025552, 0.026058, 0.026571, 0.027091, 0.027618, 0.028152, 0.028693, 0.029240, 0.029795, 0.030356, 0.030925, 0.031500, 0.032083, 0.032673, 0.033269, 0.033873, 0.034484, 0.035103, 0.035728, 0.036361, 0.037001, 0.037648, 0.038303, 0.038965, 0.039634, 0.040311, 0.040995, 0.041687, 0.042385, 0.043092, 0.043806, 0.044527, 0.045256, 0.045992, 0.046736, 0.047487, 0.048246, 0.049013, 0.049787, 0.050569, 0.051358, 0.052155, 0.052960, 0.053772, 0.054592, 0.055419, 0.056254, 0.057097, 0.057948, 0.058806, 0.059672, 0.060546, 0.061427, 0.062316, 0.063213, 0.064117, 0.065029, 0.065949, 0.066877, 0.067812, 0.068755, 0.069706, 0.070665, 0.071631, 0.072605, 0.073586, 0.074576, 0.075573, 0.076578, 0.077590, 0.078610, 0.079638, 0.080674, 0.081717, 0.082768, 0.083826, 0.084893, 0.085967, 0.087048, 0.088137, 0.089234, 0.090339, 0.091451, 0.092570, 0.093697, 0.094832, 0.095974, 0.097124, 0.098282, 0.099447, 0.100619, 0.101799, 0.102986, 0.104181, 0.105384, 0.106593, 0.107810, 0.109035, 0.110267, 0.111506, 0.112753, 0.114007, 0.115268, 0.116537, 0.117813, 0.119096, 0.120386, 0.121684, 0.122988, 0.124300, 0.125619, 0.126946, 0.128279, 0.129619, 0.130967, 0.132321, 0.133683, 0.135052, 0.136427, 0.137810, 0.139199, 0.140595, 0.141998, 0.143408, 0.144825, 0.146249, 0.147679, 0.149117, 0.150561, 0.152011, 0.153469, 0.154932, 0.156403, 0.157880, 0.159364, 0.160854, 0.162351, 0.163854, 0.165364, 0.166880, 0.168403, 0.169931, 0.171467, 0.173008, 0.174556, 0.176110, 0.177670, 0.179237, 0.180810, 0.182388, 0.183973, 0.185564, 0.187161, 0.188764, 0.190373, 0.191988, 0.193609, 0.195236, 0.196868, 0.198507, 0.200151, 0.201801, 0.203457, 0.205118, 0.206785, 0.208458, 0.210136, 0.211820, 0.213509, 0.215204, 0.216905, 0.218610, 0.220322, 0.222038, 0.223760, 0.225487, 0.227220, 0.228958, 0.230701, 0.232449, 0.234202, 0.235961, 0.237724, 0.239493, 0.241266, 0.243045, 0.244828, 0.246616, 0.248410, 0.250208, 0.252011, 0.253818, 0.255631, 0.257448, 0.259270, 0.261096, 0.262927, 0.264763, 0.266603, 0.268447, 0.270297, 0.272150, 0.274008, 0.275870, 0.277737, 0.279608, 0.281483, 0.283363, 0.285247, 0.287135, 0.289027, 0.290923, 0.292823, 0.294727, 0.296635, 0.298548, 0.300464, 0.302384, 0.304308, 0.306236, 0.308167, 0.310102, 0.312042, 0.313984, 0.315931, 0.317881, 0.319835, 0.321792, 0.323753, 0.325717, 0.327685, 0.329656, 0.331631, 0.333609, 0.335590, 0.337575, 0.339563, 0.341554, 0.343549, 0.345547, 0.347547, 0.349551, 0.351558, 0.353569, 0.355582, 0.357598, 0.359617, 0.361639, 0.363664, 0.365692, 0.367722, 0.369756, 0.371792, 0.373831, 0.375873, 0.377917, 0.379964, 0.382014, 0.384066, 0.386121, 0.388178, 0.390238, 0.392300, 0.394365, 0.396432, 0.398502, 0.400574, 0.402648, 0.404724, 0.406803, 0.408884, 0.410968, 0.413053, 0.415141, 0.417230, 0.419322, 0.421416, 0.423512, 0.425610, 0.427710, 0.429811, 0.431915, 0.434021, 0.436128, 0.438238, 0.440349, 0.442462, 0.444576, 0.446693, 0.448811, 0.450931, 0.453052, 0.455175, 0.457300, 0.459426, 0.461554, 0.463683, 0.465814, 0.467946, 0.470079, 0.472214, 0.474351, 0.476489, 0.478628, 0.480768, 0.482910, 0.485053, 0.487197, 0.489342, 0.491489, 0.493636, 0.495785, 0.497935, 0.500086, 0.502238, 0.504391, 0.506546, 0.508701, 0.510857, 0.513014, 0.515172, 0.517330, 0.519490, 0.521650, 0.523812, 0.525974, 0.528137, 0.530300, 0.532465, 0.534630, 0.536796, 0.538962, 0.541129, 0.543297, 0.545465, 0.547634, 0.549803, 0.551973, 0.554143, 0.556314, 0.558485, 0.560657, 0.562829, 0.565002, 0.567175, 0.569348, 0.571522, 0.573696, 0.575870, 0.578045, 0.580219, 0.582394, 0.584570, 0.586745, 0.588921, 0.591096, 0.593272, 0.595448, 0.597624, 0.599801, 0.601977, 0.604153, 0.606329, 0.608506, 0.610682, 0.612858, 0.615034, 0.617211, 0.619387, 0.621562, 0.623738, 0.625914, 0.628089, 0.630265, 0.632440, 0.634615, 0.636789, 0.638964, 0.641138, 0.643312, 0.645485, 0.647659, 0.649832, 0.652004, 0.654176, 0.656348, 0.658520, 0.660691, 0.662861, 0.665031, 0.667201, 0.669370, 0.671539, 0.673707, 0.675875, 0.678042, 0.680208, 0.682374, 0.684540, 0.686705, 0.688869, 0.691032, 0.693195, 0.695358, 0.697519, 0.699680, 0.701840, 0.704000, 0.706158, 0.708316, 0.710474, 0.712630, 0.714786, 0.716941, 0.719095, 0.721248, 0.723400, 0.725552, 0.727703, 0.729852, 0.732001, 0.734149, 0.736296, 0.738443, 0.740588, 0.742732, 0.744875, 0.747018, 0.749159, 0.751299, 0.753439, 0.755577, 0.757714, 0.759851, 0.761986, 0.764120, 0.766253, 0.768385, 0.770515, 0.772645, 0.774774, 0.776901, 0.779027, 0.781152, 0.783276, 0.785399, 0.787521, 0.789641, 0.791760, 0.793878, 0.795995, 0.798110, 0.800224, 0.802337, 0.804449, 0.806559, 0.808668, 0.810776, 0.812882, 0.814987, 0.817091, 0.819194, 0.821295, 0.823394, 0.825493, 0.827590, 0.829685, 0.831779, 0.833872, 0.835964, 0.838053, 0.840142, 0.842229, 0.844315, 0.846399, 0.848481, 0.850563, 0.852643, 0.854721, 0.856798, 0.858873, 0.860947, 0.863019, 0.865089, 0.867159, 0.869226, 0.871292, 0.873357, 0.875420, 0.877481, 0.879541, 0.881599, 0.883656, 0.885711, 0.887764, 0.889816, 0.891866, 0.893915, 0.895961, 0.898007, 0.900050, 0.902092, 0.904132, 0.906171, 0.908208, 0.910243, 0.912277, 0.914309, 0.916339, 0.918367, 0.920394, 0.922419, 0.924443, 0.926464, 0.928484, 0.930502, 0.932518, 0.934533, 0.936546, 0.938557, 0.940566, 0.942574, 0.944580, 0.946584, 0.948586, 0.950586, 0.952585, 0.954582, 0.956577, 0.958570, 0.960561, 0.962551, 0.964539, 0.966524, 0.968508, 0.970491, 0.972471, 0.974450, 0.976426, 0.978401, 0.980374, 0.982345, 0.984314, 0.986282, 0.988247, 0.990211, 0.992172, 0.994132, 0.996090, 0.998046, 1.000000  
};
float               RLOG_TABLE[MAX_INPUT_STEPS];


// ====================================================================================
#pragma mark - BLUETOOTH
// ====================================================================================
void BT_Process(EBluetoothCommand aCommand) {
    switch (aCommand) {
        case EBluetoothCommandApplyPatch:
            // for each input pot, get value
            for(int i = 0; i < MAX_INPUT_POTS; i++) {
                int step = gBluetoothSerial.read();
                send_analog_read_to_digipot(step, i);
            }
            break;
        case EBluetoothCommandSetPotValue:
            break;
        case EBluetoothCommandToggleLoop:
            break;
        case EBluetoothCommandSavePatch:
            break;
        case EBluetoothCommandResetBank:
            break;
        default:
            break;
    }
    
}


void read_remote() {
    if(gBluetoothSerial.available()) {
        EBluetoothCommand command = (EBluetoothCommand)gBluetoothSerial.read();
        BT_Process(command);
    }
}


void send_analog_read_to_remote(int aAnalogStep, uint8_t aDigipotIndex) {
    while(gBluetoothSerial.available() == false)
        ;
    gBluetoothSerial.write(EBluetoothCommandSetPotValue);
    gBluetoothSerial.write(aDigipotIndex);
    gBluetoothSerial.write(aAnalogStep);
}


void generate_lookup_tables() {
    Serial.println("generate_lookup_tables");
    for(int i = 0; i < MAX_INPUT_STEPS ; i++) {
        float j = (float)((float)(i + 1) / (float)MAX_INPUT_STEPS);
        Serial.println(j, DEC);
        j = 1 - (1 / (j * j));
        float ilog = exp(j);
        Serial.println(ilog, DEC);
        LOG_TABLE[i] = ilog;
    }
    Serial.println("LOG_TABLE:");
    for(int i = 0; i < MAX_INPUT_STEPS; i++) {
        Serial.println(LOG_TABLE[i], DEC);
    }
}


void send_analog_read_to_digipot(float aAnalogStep, uint8_t aDigipotIndex) {

    // translate input value to output value, taking account of max output value and step differences
    // int input_step = (INPUT_TYPE[aDigipotIndex] == EPotLog) ? (aAnalogStep * LOG_TABLE[(int)aAnalogStep]) : aAnalogStep;
    int input_step = aAnalogStep;
    
    float input_ohm_per_step = gPots[aDigipotIndex].inputvalue / MAX_INPUT_STEPS;
    float output_ohm_per_step = gPots[aDigipotIndex].outputvalue / MAX_OUTPUT_STEPS;
    float digistep = (input_step * input_ohm_per_step) / output_ohm_per_step;
    
    
    // debug
    Serial.print((char *)"\nRead ");
    Serial.print(gPots[aDigipotIndex].name);
    Serial.print((char *)": input step=");
    Serial.print(aAnalogStep, DEC);
    Serial.print((char *)" --> output step=");
    Serial.print(digistep, DEC);
    
    // send value to digipot : step index (digistep)
//    Wire.beginTransmission(gPots[aDigipotIndex].outputaddress); // transmit to device #address
//    Wire.write((uint8_t)0x00);     // sends instruction byte
//    Wire.write((uint8_t)digistep);       // sends potentiometer value byte
//    Wire.endTransmission();     // stop transmitting
    
    gPots[aDigipotIndex].currentstep = digistep;
    delay(50);
}

unsigned long gLEDTimeMS;
bool gIsStatusON;

void setup_amp() {
    Serial.println("setup_amp");
    
    //generate_lookup_tables();
  
    Wire.begin();
    
    init_pot_data();
    
    gLEDTimeMS = millis();
    pinMode(PIN_STATUS_LED, OUTPUT);
    gIsStatusON = false;
}



void loop_amp() {
    
    //Serial.println("loop_amp");

    
    if(millis() - gLEDTimeMS > 500) {
        digitalWrite(PIN_STATUS_LED,  gIsStatusON ? LOW : HIGH);
        gIsStatusON = !gIsStatusON;
        gLEDTimeMS = millis();
    }
    
    
    // for each physical pot on amp
    for(int i = 0; i < MAX_INPUT_POTS; i++) {
        // read pot value (between 0 and MAX_INPUT_STEPS)
        int step = analogRead(gPots[i].inputaddress);
        
        Serial.print("Read input ");
        Serial.print(i, DEC);
        Serial.print(" (addr ");
        Serial.print(gPots[i].inputaddress, DEC);
        Serial.print("): ");
        Serial.println(step, DEC);

        
        // send step to digipot if a change occured
//        if(step != gPots[i].currentstep) {
//            
//            // value has changed, convert and send value to digital pot TODO: maybe should be done at each loop ?
//            send_analog_read_to_digipot(step, i);
//            
//            // value has changed, send it to remote
//            send_analog_read_to_remote(step, i);
//        }
    }
    
    // listen to remote commands
//    read_remote();
    
    delay(10);
}

